
import 'package:collection/collection.dart';
import 'package:flutter/foundation.dart';

import '../dao/ImMessageDao.dart';
import '../dao/ImMessageSendDao.dart';
import '../dao/ImUserDao.dart';
import '../pojo/ImPojo.dart';
import '../socket/dto/business/Message.dart';
import '../util/ImConstant.dart';
import '../util/IteraterUtil.dart';
import '../util/UiUtil.dart';
import 'BaseService.dart';
import 'ImMessageRefService.dart';
import 'ImMessageService.dart';

class MessageReceiveService extends BaseService {

  // final _imMessageDao = ImMessageDao();
  // final _imMessageSendDao = ImMessageSendDao();

  /// 接受服务端转发的消息
  Future<ImMessage> handleReceiveMessage(String userId, MessageObject messageObject) async {
    Set<String> refServerIds = messageObject.refMessageIds?.split(",").toSet()??(new Set<String>());

    List<MessageObject> allMessageObjects = [];
    allMessageObjects.add(messageObject);

    // 拉取引用的消息
    if (refServerIds != null) {
      ImMessageRefService messageRefService = ImMessageRefService();
      List<String> refIds = IteraterUtil.changeSet(refServerIds).toList();
      List<MessageObject> refMessages = await messageRefService.pullRefMessages(userId, refIds);
      allMessageObjects.addAll(refMessages);
    }

    // var imMessages = await compute(saveMessage2, SaveMessageParam(userId: userId, messageObjects: allMessageObjects));
    var imMessages = await saveMessage2(SaveMessageParam(userId: userId, messageObjects: allMessageObjects));
    // var imMessages = await IsolatePoolUtil.getInstance().compute(saveMessage, SaveMessageParam(userId: userId, messageObjects: allMessageObjects));
    return imMessages[0];
  }

  Future<void> handleReadMessages(String userId, List<String> messageIds) async {
    var uiUpdateMessages = await doReadMessage2(ReadMessageParam(userId: userId, messageIds: messageIds));
    // var uiUpdateMessages = await IsolatePoolUtil.getInstance().compute(doReadMessages, ReadMessageParam(userId:
    //   userId, messageIds: messageIds));

    UiUtil.uiUpdateMessages(uiUpdateMessages);
  }

  Future<void> handleWithdrawMessages(String userId, List<String> messageIds) async {
    final imMessageDao = ImMessageDao();
    final imMessageSendDao = ImMessageSendDao();

    var uiUpdateMessages = <ImMessage>[];
    for (String id in messageIds) {
      ImMessage? message = await imMessageDao.getByServerIdAndUserId(id, userId);
      uiUpdateMessages.add(message!);
      imMessageDao.updateMessageStatus(message!.id!, ImMessageStatus.withdrawed, ImMessageActionStatus.withdrawed);
    }
    UiUtil.uiUpdateMessages(uiUpdateMessages);
  }

  Future<List<ImMessage>> saveMessage2(SaveMessageParam param) async {
    ImMessageService messageService = ImMessageService();
    List<ImMessage> imMessages = await messageService.saveOrUpdates(param.userId, param.messageObjects, false);
    return imMessages;
  }
}

Future<List<ImMessage>> saveMessage(SaveMessageParam param) async {
  ImMessageService messageService = ImMessageService();
  List<ImMessage> imMessages = await messageService.saveOrUpdates(param.userId, param.messageObjects, false);
  return imMessages;
}

Future<List<ImMessage>> doReadMessages(ReadMessageParam param) async {
  return doReadMessage2(param);
}

Future<List<ImMessage>> doReadMessage2(ReadMessageParam param) async {
  final imMessageDao = ImMessageDao();
  final imMessageSendDao = ImMessageSendDao();
  final imUserDao = ImUserDao();

  Set<int> updateMessageIdSet = new Set();  // 发送者收到已读消息

  List<ImMessageSend> p2gFromUserMessageSendList = [];  // (群消息)发送者收到已读消息
  List<ImMessage> uiUpdateMessages = [];
  for (String id in param.messageIds) {
    if (id.contains(ImConstant.MESSAGE_SPLIT)) {
      List<String> keys = id.split(ImConstant.MESSAGE_SPLIT);
      String serverId = keys[0];
      String toUserId = keys[1];
      ImMessage? message = await imMessageDao.getByServerIdAndUserId(serverId, param.userId);
      if (message!.isSender(param.userId)) { // 发送者
        List<ImMessageSend> messageSends = await imMessageSendDao.getByMessageId(message.id!);
        ImMessageSend? messageSend = messageSends.firstWhereIndexedOrNull((i, m)=> m.userId == toUserId);
        //await imMessageSendDao.getByMessageIdAndUserId(message.id!, toUserId);
        if (messageSend != null) {
          messageSend.actionStatus = ImMessageActionStatus.readed;
          messageSend.updateTime = DateTime.now();
          p2gFromUserMessageSendList.add(messageSend);
        }

        int readSize = messageSends.where((ms)=>ms.actionStatus == ImMessageActionStatus.readed).length;
        if (readSize == messageSends.length) {
          message.actionStatus = ImMessageActionStatus.readed;
          message.status = ImMessageStatus.readed;
          await imMessageDao.updateMessageStatus(message.id!, ImMessageStatus.readed, ImMessageActionStatus.readed);
        }
      } else {
        updateMessageIdSet.add(message.id!);
      }
    } else {
      ImMessage? message = await imMessageDao.getByServerIdAndUserId(id, param.userId);
      message!.fromImUser = await imUserDao.getByUserId(message!.fromUserId);
      await imMessageDao.loadRefMessage(message!);
      uiUpdateMessages.add(message!);
      if (message.isSender(param.userId)) {
        updateMessageIdSet.add(message.id!);
        message.actionStatus = ImMessageActionStatus.readed;
      } else {
        // updateMessageIdSet.add(message.id!);
        message.actionStatus = ImMessageActionStatus.readed;
        message.status = ImMessageStatus.readed;
        await imMessageDao.updateMessageStatus(message.id!, ImMessageStatus.readed, ImMessageActionStatus.readed);
      }
    }
  }

  await imMessageDao.changeMessageActionStatus(updateMessageIdSet, ImMessageActionStatus.readed);
  await imMessageSendDao.batchUpdates(p2gFromUserMessageSendList);

  return uiUpdateMessages;
}

class SaveMessageParam {
  String userId;
  List<MessageObject> messageObjects;

  SaveMessageParam({ required this.userId, required this.messageObjects});
}

class ReadMessageParam {
  String userId;
  List<String> messageIds;

  ReadMessageParam({ required this.userId, required this.messageIds});
}



